/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.texture;

import com.android1.amarena2d.engine.EngineObject;
import com.android1.amarena2d.engine.Resource;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractTextureAtlas extends EngineObject implements TextureAtlas {

    protected final Resource.Manager resourceManager = new Resource.Manager(this);

    protected ManagedTexture managedTexture;
    protected ArrayList<AtlasTextureFrame> textureFrames;
    private int index = 0;
    private AtlasMesh atlasMesh;
    protected boolean init;

    protected AbstractTextureAtlas() {
        this.textureFrames = new ArrayList<AtlasTextureFrame>(50);
    }

    protected AbstractTextureAtlas(ManagedTexture managedTexture) {
        this();
        this.managedTexture = managedTexture;

    }

    public AtlasTextureFrame add(AtlasTextureFrame atlasTextureFrame) {
        return add(atlasTextureFrame.getTag(), atlasTextureFrame);
    }

    public AtlasTextureFrame add(String tag, AtlasTextureFrame atlasTextureFrame) {
        if (init)
            throw new IllegalStateException("TextureAtlas has already been build.");
        this.textureFrames.add(atlasTextureFrame);
        atlasTextureFrame.setTag(tag);
        return atlasTextureFrame;
    }

    protected int nextIndex() {
        return index++;
    }

    @Override
    public AtlasTextureFrame findTextureFrame(String tag) {
        for (int i = 0; i < textureFrames.size(); i++) {
            AtlasTextureFrame atlasTextureFrame = textureFrames.get(i);
            if (atlasTextureFrame.getTag() != null && atlasTextureFrame.getTag().equals(tag))
                return atlasTextureFrame;
        }
        return null;
    }

    @Override
    public boolean contains(String tag) {
        for (int i = 0; i < textureFrames.size(); i++) {
            AtlasTextureFrame atlasTextureFrame = textureFrames.get(i);
            if (atlasTextureFrame.getTag() != null && atlasTextureFrame.getTag().equals(tag))
                return true;
        }
        return false;
    }

    @Override
    public List<AtlasTextureFrame> getTextureFrames() {
        return textureFrames;
    }

    @Override
    public AtlasTextureFrame getTextureFrame(int index) {
        return textureFrames.get(index);
    }

    @Override
    public ManagedTexture getManagedTexture() {
        return managedTexture;
    }

    @Override
    public AtlasMesh getAtlasMesh() {
        if (this.atlasMesh == null){
            this.atlasMesh = new AtlasMesh(this);
        }
        return this.atlasMesh;
    }


    protected boolean canDispose() {
        return isInit() && resourceManager.canDispose();
    }

    @Override
    public void obtainRef(Consumer consumer) {
        resourceManager.obtainRef(consumer);
    }

    @Override
    public void releaseRef(Consumer consumer) {
        resourceManager.releaseRef(consumer);
    }

    @Override
    public void releaseAllRefs() {
        resourceManager.releaseAllRefs();
    }

    @Override
    public boolean hasRefs() {
        return resourceManager.hasRefs();
    }

    @Override
    public void register(StateListener listener) {
        resourceManager.register(listener);
    }

    @Override
    public void unregister(StateListener listener) {
        resourceManager.unregister(listener);
    }

    @Override
    public void markPersistent() {
        resourceManager.markPersistent();
    }

    @Override
    public void revokePersistent() {
        resourceManager.revokePersistent();
    }

    @Override
    public boolean isEagerDispose() {
        return resourceManager.isEagerDispose();
    }

    @Override
    public void setEagerDispose(boolean dispose) {
        resourceManager.setEagerDispose(dispose);
    }

    @Override
    public boolean equalResource(Resource otherResource) {
        return this == otherResource;
    }

    @Override
    public void init() {
        if (!isInit()) {
            this.init = true;
            this.managedTexture.obtainRef(this);
            this.managedTexture.init();
            if (this.atlasMesh != null) {
                this.atlasMesh.obtainRef(this);
                this.atlasMesh.init();
            }
            resourceManager.init();
        }
    }

    @Override
    public void dispose() {
        if (canDispose()) {
            this.init = false;
            this.managedTexture.releaseRef(this);
            this.managedTexture.dispose();
            if (this.atlasMesh != null) {
                this.atlasMesh.releaseRef(this);
                this.atlasMesh.dispose();
            }
            resourceManager.dispose();
        }
    }

    @Override
    public boolean isInit() {
        return init;
    }
}